package io.coderyeah.ymcc.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import io.coderyeah.ymcc.constant.MQConstants;
import io.coderyeah.ymcc.constant.YmccConstants;
import io.coderyeah.ymcc.domain.*;
import io.coderyeah.ymcc.dto.CourseParamDTO;
import io.coderyeah.ymcc.dto.PreOrderDTO;
import io.coderyeah.ymcc.dto.StationInMQDTO;
import io.coderyeah.ymcc.enums.YmccSystemError;
import io.coderyeah.ymcc.exception.BusinessException;
import io.coderyeah.ymcc.feign.client.MediaServiceClient;
import io.coderyeah.ymcc.feign.client.SearchServiceClient;
import io.coderyeah.ymcc.feign.client.UserServiceClient;
import io.coderyeah.ymcc.mapper.*;
import io.coderyeah.ymcc.result.JSONResult;
import io.coderyeah.ymcc.service.ICourseService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import io.coderyeah.ymcc.service.ICourseUserLearnService;
import io.coderyeah.ymcc.util.AssertUtil;
import io.coderyeah.ymcc.vo.CourseDetailVo;
import io.coderyeah.ymcc.vo.CourseInfoVo;
import io.coderyeah.ymcc.vo.CourseStateVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author coderyeah
 * @since 2022-10-23
 */
@Slf4j
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private CourseDetailMapper detailMapper;
    @Autowired
    private CourseMarketMapper marketMapper;
    @Autowired
    private CourseResourceMapper resourceMapper;
    @Autowired
    private CourseTeacherMapper teacherMapper;
    @Autowired
    private CourseSummaryMapper summaryMapper;
    @Autowired
    private TeacherMapper mapper;
    @Autowired
    private CourseChapterMapper chapterMapper;
    @Autowired
    private SearchServiceClient searchServiceClient;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private UserServiceClient userServiceClient;

    @Autowired
    private MediaServiceClient mediaServiceClient;

    @Autowired
    private CourseUserLearnMapper learnMapper;

    @Autowired
    private ICourseUserLearnService learnService;

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;


    @Transactional
    @Override
    public JSONResult saveCourse(CourseParamDTO courseDTO) {
        // 保存课程
        Course course = addCourse(courseDTO);
        // 初始化课程概要
        addCourseSummary(course);
        // 保存课程详情
        addCourseDetail(courseDTO, course);
        // 保存课程营销
        addCourseMarket(courseDTO, course);
        // 保存课程资源
        addCourseResource(courseDTO, course);
        // 保存讲师
        addCourseTeacher(courseDTO, course);
        return JSONResult.success();
    }

    private Course addCourse(CourseParamDTO courseDTO) {
        Course course = courseDTO.getCourse();
        // 默认课程下线
        course.setStatus(Course.STATUS_OFFLINE);
        course.setChapterCount(0);
        // todo 添加人
        // 保存讲师们的名字
        StringBuffer buffer = new StringBuffer();
        List<Teacher> teachers = mapper.selectBatchIds(courseDTO.getTeacherIds());
        teachers.forEach(teacher -> {
            buffer.append(teacher.getName()).append(",");
        });
        // 删除末尾逗号
        buffer.deleteCharAt(buffer.lastIndexOf(","));
        course.setTeacherNames(buffer.toString());
        courseMapper.insert(course);
        return course;
    }

    private void addCourseSummary(Course course) {
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(course.getId());
        summaryMapper.insert(courseSummary);
    }

    private void addCourseDetail(CourseParamDTO courseDTO, Course course) {
        CourseDetail courseDetail = courseDTO.getCourseDetail();
        courseDetail.setId(course.getId());
        detailMapper.insert(courseDetail);
    }

    private void addCourseMarket(CourseParamDTO courseDTO, Course course) {
        CourseMarket courseMarket = courseDTO.getCourseMarket();
        if (courseMarket.getPrice() == null) {
            courseMarket.setPrice(new BigDecimal(0));
        }
        courseMarket.setId(course.getId());
        marketMapper.insert(courseMarket);
    }

    private void addCourseResource(CourseParamDTO courseDTO, Course course) {
        CourseResource courseResource = courseDTO.getCourseResource();
        courseResource.setCourseId(course.getId());
        resourceMapper.insert(courseResource);
    }

    private void addCourseTeacher(CourseParamDTO courseDTO, Course course) {
        List<Long> teacherIds = courseDTO.getTeacherIds();
        teacherIds.forEach(tid -> {
            CourseTeacher courseTeacher = new CourseTeacher();
            courseTeacher.setCourseId(course.getId());
            courseTeacher.setTeacherId(tid);
            teacherMapper.insert(courseTeacher);
        });
    }

    @Override
    public void onLineCourse(Long id) {
        // 通过id查询指定课程
        Course course = selectById(id);
        AssertUtil.isNotNull(course, YmccSystemError.COURSE_NOT_EXIST.getMessage());
        // 查询课程营销
        CourseMarket courseMarket = marketMapper.selectById(id);
        // 查询课程概要
        CourseSummary courseSummary = summaryMapper.selectById(id);
        // 修改课程状态为上架
        course.setStatus(Course.STATUS_ONLINE);
        course.setOnlineTime(new Date()); // 上架时间
        updateById(course);
        // 拷贝存入ES的对象
        CourseDoc courseDoc = copy(course, courseMarket, courseSummary);
        // 调用接口存入es索引库
        searchServiceClient.save(courseDoc);
        log.info("课程已上架~~~");
        // 利用MQ发布站内信
        send2MQ(id, course);
    }

    private void send2MQ(Long id, Course course) {
        StationInMQDTO mqdto = new StationInMQDTO();
        mqdto.setContent(String.format(YmccConstants.STATION_CONTENT, id, course.getName()));
        mqdto.setTitle(YmccConstants.STATION_TITLE);
        mqdto.setType(YmccConstants.STATION_TYPE);
        // 查询需要发送的用户获取id
        List<User> userList = JSON.parseArray(JSON.toJSONString(userServiceClient.list().getData()), User.class);
        // 获取ids
        List<Long> ids = userList.stream().map(User::getId).collect(Collectors.toList());
        log.info("ids:{}", ids);

        log.info("站内信内容:{}", String.format(YmccConstants.STATION_CONTENT, id, course.getName()));
        mqdto.setIds(ids);
        // 将对象转换成json字符串
        String s = JSON.toJSONString(mqdto);
        Message<String> message = MessageBuilder.withPayload(s).build();
        rocketMQTemplate.syncSend(MQConstants.MQ_COURSE_TOPIC + ":" + MQConstants.MQ_COURSE_TAGS, message);
    }

    private CourseDoc copy(Course course, CourseMarket courseMarket, CourseSummary courseSummary) {
        CourseDoc courseDoc = new CourseDoc();
        BeanUtils.copyProperties(course, courseDoc);
        BeanUtils.copyProperties(courseMarket, courseDoc);
        BeanUtils.copyProperties(courseSummary, courseDoc);
        courseDoc.setChargeName(courseMarket.getCharge() == 1 ? YmccConstants.FREE : YmccConstants.CHARGE);
        return courseDoc;
    }

    @Override
    public void offLineCourse(Long id) {
        // 下架课程
        // 修改状态
        Course course = selectById(id);
        course.setStatus(Course.STATUS_OFFLINE);
        course.setEndTime(new Date());
        updateById(course);
        // 通过id删除索引文档
        searchServiceClient.deleteById(id);
        log.info("课程下架成功~~~");
    }

    @Override
    public CourseDetailVo courseDetailVo(Long id) {
        Course course = checkData(id);
        // 查询营销数据
        CourseMarket courseMarket = marketMapper.selectById(id);
        // 查询课程详情
        CourseDetail courseDetail = detailMapper.selectById(id);
        // 查询该课程的老师
        Wrapper<CourseTeacher> wrapper = new EntityWrapper<>();
        wrapper.eq("course_id", id);
        List<CourseTeacher> courseTeachers = teacherMapper.selectList(wrapper);
        List<Long> tids = courseTeachers.stream().map(CourseTeacher::getTeacherId).collect(Collectors.toList());
        // 通过id获取到教授此课程所有老师
        List<Teacher> teachers = mapper.selectBatchIds(tids);
        // 根据课程id找到对应章节
        Wrapper<CourseChapter> wrapper2 = new EntityWrapper<>();
        wrapper.eq("course_id", id);
        List<CourseChapter> courseChapters = chapterMapper.selectList(wrapper2);
        // 通过课程id获取到属于该课程的所有媒体数据[使用openfeign]
        JSONResult jsonResult = mediaServiceClient.getByCourseId(id);
        if (null == jsonResult) {
            throw new BusinessException(YmccSystemError.SYSTEM_PARAM_ERROR);
        }
        String jsonString = JSON.toJSONString(jsonResult.getData());
        // 转换为集合 得到本课程下所有的媒体数据
        List<MediaFile> mediaFiles = JSON.parseArray(jsonString, MediaFile.class);
        // 将所有章节转换为map
        Map<Long, CourseChapter> map = courseChapters.stream().collect(Collectors.toMap(CourseChapter::getId, e -> e));
        // 遍历媒体数据
        mediaFiles.forEach(m -> {
            m.setFileUrl(null);
            CourseChapter courseChapter = map.get(m.getChapterId());
            assert courseChapter != null;
            courseChapter.getMediaFiles().add(m);
        });
        // 查询courseSummary
        CourseSummary courseSummary = summaryMapper.selectById(id);
        // 封装返回结果
        CourseDetailVo detailVo = new CourseDetailVo();
        detailVo.setCourseDetail(courseDetail);
        detailVo.setCourse(course);
        detailVo.setTeachers(teachers);
        detailVo.setCourseMarket(courseMarket);
        detailVo.setCourseChapters(courseChapters);
        detailVo.setCourseSummary(courseSummary);
        return detailVo;
    }

    private Course checkData(Long id) {
        if (null == id) {
            throw new BusinessException(YmccSystemError.SYSTEM_PARAM_ERROR);
        }
        // 根据id查询课程信息
        Course course = courseMapper.selectById(id);
        // 判断是否存在
        if (null == course) {
            throw new BusinessException(YmccSystemError.SYSTEM_PARAM_ERROR);
        }
        return course;
    }

    @Override
    public JSONResult getCourseStateById(Long id) {
        // 根据课程id检查课程状态
        AssertUtil.isNotNull(id, YmccSystemError.INVALID_REQUEST_PARAMETER.getMessage());
        Course course = selectById(id);
        // 查询课程营销 看是否收费
        CourseMarket courseMarket = marketMapper.selectById(id);
        // 获取登陆人id FIXME
        Long loginId = 3L;
        // 通过登录用户和课程id查询是否购买
        Wrapper<CourseUserLearn> wrapper = new EntityWrapper<>();
        wrapper.eq("login_id", loginId);
        wrapper.eq("course_id", id);
        CourseUserLearn userLearn = learnService.selectOne(wrapper);

        CourseStateVo courseStateVo = new CourseStateVo();
        courseStateVo.setIsOnline(Objects.equals(course.getStatus(), Course.STATUS_ONLINE));// 是否上线
        courseStateVo.setIsFree(courseMarket.getCharge() == 1);// 免费
        courseStateVo.setIsBuy(userLearn != null && userLearn.getState() == 0);// 是否购买
        return JSONResult.success(courseStateVo);
    }

    @Override
    public JSONResult getCourseInfo(List<Long> ids) {
        AssertUtil.isNotNull(ids, YmccSystemError.INVALID_REQUEST_PARAMETER.getMessage());
        // 通过id查询课程信息
        List<Course> courseInfos = courseMapper.selectBatchIds(ids);
        List<CourseMarket> courseMarkets = marketMapper.selectBatchIds(ids);
        Map<Long, CourseMarket> marketMap = courseMarkets.stream().collect(Collectors.toMap(CourseMarket::getId, e -> e));
        courseInfos.forEach(c -> {
            c.setCourseMarket(marketMap.get(c.getId()));
        });

        BigDecimal totalAmount = BigDecimal.ZERO;
        for (CourseMarket courseMarket : courseMarkets) {
            totalAmount = totalAmount.add(courseMarket.getPrice());
        }

        CourseInfoVo courseInfoVo = new CourseInfoVo(totalAmount, courseInfos);

        log.info("totalAmount:{}", totalAmount);
        return JSONResult.success(courseInfoVo);
    }


    @Override
    public CourseInfoVo courseOrderKillInfo(String orderNo) {
        //1.数据的校验
        AssertUtil.isNotEmpty(orderNo, "非法的请求");

        PreOrderDTO preOrder = (PreOrderDTO) redisTemplate.opsForValue().get(orderNo);
        assert preOrder != null;
        Course course = selectById(preOrder.getCourseId());

        CourseMarket courseMarket = marketMapper.selectById(preOrder.getCourseId());
        courseMarket.setPrice(preOrder.getKillPrice());
        course.setCourseMarket(courseMarket);
        List<Course> list = new ArrayList<>();
        list.add(course);
        //返回数据
        return new CourseInfoVo(preOrder.getKillPrice(),list);
    }
}
